package com.intel.factorytest.ChamberMode;

import java.io.IOException;

import android.app.Activity;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.app.ActionBar;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.Window;
import android.os.SystemProperties;
import android.os.CountDownTimer;
import android.os.Looper;
import android.app.StatusBarManager;
import android.view.KeyEvent;
import android.content.Context;

import com.intel.factorytest.R;
import com.intel.factorytest.util.LogUtils;
import com.intel.factorytest.util.Util;
import com.intel.factorytest.util.ShellUtilsPlus;
import com.intel.factorytest.ChamberMode.ChamberModeMainActivity;


public class FrontCameraTest extends Activity implements SurfaceHolder.Callback {
    private Button mStartButton;
    private Button mStopButton;
    private TextView mShowText;
    Context mContext;

    private SurfaceView mCameraView = null;
    private TextView mcTestText;
    private android.hardware.Camera mCameraDevice = null;
    SurfaceHolder holder;
    private int cameraId = 0;
    ActionBar  actionBar;
    private int mTimeout = 20000;
    private FrontCameraDown mFrontCameraDown = null;
    //private static final int START_FRONT_CAMERA_TEST_RESULT_CODE = 1;
    private LinearLayout mButtonView;    
    StatusBarManager mStatusBarManager;
    private boolean isShowButton = true;
    
    private static final int FRONT_CAMERA_MSG_UPDATE_UI = 1;
    private static final int FRONT_CAMERA_MSG_TEST_END = 2;
    
    private Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case FRONT_CAMERA_MSG_TEST_END: {                    
                    removeMessages(FRONT_CAMERA_MSG_TEST_END);                    
                    Util.isFrontCameraTesting = false ;
                    SystemProperties.set("persist.sys.chamber_run","true");
                    finish();
                    break;
                }
                case FRONT_CAMERA_MSG_UPDATE_UI: {
                     removeMessages(FRONT_CAMERA_MSG_UPDATE_UI);
                     updateShowUI("");
                    break;
                }
                default:
                    break;
            }
        }
    };

    public void onCreate(Bundle b) {
        super.onCreate(b);
        LogUtils.logi( "onCreate ");        
        mContext = getApplicationContext(); 
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
        Util.wakeUpAndKeepScreenOn(this);
        Util.setWindowBrightness(this,WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_FULL);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.chamber_mode_camera_test);
        mStatusBarManager = (StatusBarManager)getSystemService(STATUS_BAR_SERVICE);
        initView();

        mCameraView = (SurfaceView) findViewById(R.id.cameraView);
        
        mcTestText = new TextView(this);
        mcTestText.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
                LayoutParams.FILL_PARENT));
        mcTestText.setGravity(Gravity.CENTER);
        mcTestText.setTextSize(16);

        cameraId = 0;
        if (2 == android.hardware.Camera.getNumberOfCameras()) {
            try {
                mCameraDevice = android.hardware.Camera.open(1);// for the small
                cameraId = 1;
            } catch (Exception e) {
                mcTestText.setText("The front camera is not available");
                setContentView(mcTestText);
            }

        } else if (1 == android.hardware.Camera.getNumberOfCameras()) {
            android.hardware.Camera.CameraInfo cameraInfo = new android.hardware.Camera.CameraInfo();
            android.hardware.Camera.getCameraInfo(0, cameraInfo);
            if (android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT == cameraInfo.facing) {
                mCameraDevice = android.hardware.Camera.open(0);// for the small
                cameraId = 0;
            } else {
                mcTestText.setText("The front camera is not available");
                FrontCameraTest.this.setContentView(mcTestText);
            }
        } else {// not available camera
            mcTestText.setText("Not available camera");
            FrontCameraTest.this.setContentView(mcTestText);
        }

        holder = mCameraView.getHolder();
        holder.addCallback(this);
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

    }

    protected void initView() {
        LogUtils.loge("initView");
        mShowText = (TextView) findViewById(R.id.showtext);
        mStartButton = (Button) findViewById(R.id.start);
        mStopButton = (Button) findViewById(R.id.stop);
        mStartButton.setEnabled(false);
        mStopButton.setEnabled(false);
        if(isShowButton) {
            mButtonView = (LinearLayout)findViewById(R.id.bottom);
            mButtonView.setVisibility(View.GONE);
        }

        mStartButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                v.setClickable(false);
                finish();
            }
        });

        mStopButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                v.setClickable(false);
                finish();
            }
        });
    }

    public void HideBottomMenu(){
        LogUtils.logi( "HideBottomMenu");
        mStatusBarManager.disable(StatusBarManager.DISABLE_MASK);
        actionBar = getActionBar();
        if(actionBar != null) {
               actionBar.hide();
        }
        View decorView = this.getWindow().getDecorView();        
        int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_IMMERSIVE
                | View.SYSTEM_UI_FLAG_FULLSCREEN;
        decorView.setSystemUiVisibility(uiOptions);
        decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
                    @Override
                    public void onSystemUiVisibilityChange(int visibility) {
                        actionBar = getActionBar();
                        if(actionBar != null) {
                            actionBar.hide();
                        }
                        View decorView = getWindow().getDecorView();
                        int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                                | View.SYSTEM_UI_FLAG_IMMERSIVE
                                | View.SYSTEM_UI_FLAG_FULLSCREEN;
                        decorView.setSystemUiVisibility(uiOptions);
                    }
            });
    }
    /*
        public void setWindowBrightness(float brightness) {
            Window window = getWindow();
            WindowManager.LayoutParams lp = window.getAttributes();
            lp.screenBrightness = brightness;
            window.setAttributes(lp);
        }
    */
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if ((keyCode == KeyEvent.KEYCODE_BACK) || (keyCode == KeyEvent.KEYCODE_VOLUME_UP) || (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)){
           return true;
        }
        return super.onKeyDown(keyCode, event);
    }
    
    public void sendDelayedMsg(int msg, long delayMillis, String putString, String value){        
        LogUtils.logi( "sendDelayedMsg msg = " + msg + ",delaytime = " + delayMillis + ",putString = " + putString + ",value = " + value);
        if(!TextUtils.isEmpty(putString)&&!TextUtils.isEmpty(value)){
            Bundle b = new Bundle();
            b.putString(putString, value);
            Message m = Message.obtain(mHandler, msg);
            m.setData(b);
            mHandler.sendMessageDelayed(m, delayMillis);
        }else{
            Message m = Message.obtain(mHandler, msg);
            mHandler.sendMessageDelayed(m, delayMillis);
        }
    }
    
    public void updateShowUI(String text) {        
        LogUtils.logi( "updateShowUI text = " + text);
        mShowText.setText(text);
    }

    public int getDisplayRotation(Activity activity) {
        int rotation = activity.getWindowManager().getDefaultDisplay()
                .getRotation();
        switch (rotation) {
        case Surface.ROTATION_0:
            return 0;
        case Surface.ROTATION_90:
            return 90;
        case Surface.ROTATION_180:
            return 180;
        case Surface.ROTATION_270:
            return 270;
        }
        return 0;
    }

    public int getDisplayOrientation(int degrees, int cameraId) {
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(cameraId, info);
        int result;
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
            result = (360 - result) % 360;
           LogUtils.logd("info.orientation = " + info.orientation
                    + "  degrees = " + degrees + " result = " + result);
        } else {
            result = (info.orientation - degrees + 360) % 360;
            LogUtils.logd("info.orientation = " + info.orientation
                    + "  degrees = " + degrees + " result = " + result);
        }
        return result;
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        if (mCameraDevice != null) {
            mCameraDevice.setDisplayOrientation(getDisplayOrientation(
                    getDisplayRotation(this), cameraId));
        }
    }

    public void onResume() {
        super.onResume();
        LogUtils.logi( "onResume ");
        SystemProperties.set("sys.cit.key.test","true");        
        SystemProperties.set("persist.sys.chamber_run","false");
        HideBottomMenu();
        mStartButton.setEnabled(true);
        mStopButton.setEnabled(true);
        Util.isFrontCameraTesting = true;
        updateShowUI("Front Camera");
        sendDelayedMsg(FRONT_CAMERA_MSG_UPDATE_UI,5000,null,null); 
        if (mTimeout > 0){
            LogUtils.logi("startFrontCameraTest 20s");
            new countDownThread().start();
        }
        // switch camera to the front one
        if (mCameraDevice == null)
            openCamerawithholder();
        //android.os.SystemProperties.set("service.camera.id", "1");
        LogUtils.loge("openCamerawithholder ok");
        try {
            mCameraDevice.startPreview();
            mCameraDevice.setDisplayOrientation(getDisplayOrientation(
                    getDisplayRotation(this), cameraId));
        } catch (NullPointerException e) {
            e.printStackTrace(System.err);
        }
    }

    private void openCamerawithholder() {
        cameraId = 0;
        if (2 == android.hardware.Camera.getNumberOfCameras()) {
            try {
                mCameraDevice = android.hardware.Camera.open(1);// for the small
                cameraId = 1;
            } catch (Exception e) {
                mcTestText.setText("The front camera is not available");
                setContentView(mcTestText);
            }

        } else if (1 == android.hardware.Camera.getNumberOfCameras()) {
            android.hardware.Camera.CameraInfo cameraInfo = new android.hardware.Camera.CameraInfo();
            android.hardware.Camera.getCameraInfo(0, cameraInfo);

            if (android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT == cameraInfo.facing) {
                mCameraDevice = android.hardware.Camera.open(0);// for the small
                cameraId = 0;
            } else {
                mcTestText.setText("The front camera is not available");
                FrontCameraTest.this.setContentView(mcTestText);
            }
        } else {// not available camera
            mcTestText.setText("Not available camera");
            FrontCameraTest.this.setContentView(mcTestText);
        }
        try {
            mCameraDevice.setPreviewDisplay(holder);
            mCameraView.setVisibility(View.VISIBLE);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    public void onPause() {
        super.onPause();        
        LogUtils.logd( "onPause() ");
        SystemProperties.set("sys.cit.key.test","false");
        if ( mFrontCameraDown != null ) mFrontCameraDown.cancel();
        
        if (mCameraDevice != null) {
            mCameraDevice.stopPreview();
            mCameraDevice.release();
            mCameraDevice = null;
        }
        LogUtils.logd( "end onPause");
        //android.os.SystemProperties.set("service.camera.id", "0");
    }

    /**
     * total 3 states, before preview, previewing, after capture ,
     */

    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        LogUtils.logi( "surfaceChanged width=" + width + " height=" + height);
        if (mCameraDevice != null) {
            try {
                mCameraDevice.setPreviewDisplay(holder);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    public void surfaceCreated(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        LogUtils.logi( "surfaceCreated ");
        //mCameraDevice.startPreview();

    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        LogUtils.logi( "surfaceDestroyed ");
        if (mCameraDevice != null) {
            mCameraDevice.stopPreview();

            mCameraDevice.release();
            mCameraDevice = null;
        }
        holder.removeCallback(this);  
    }

    @Override
    public void finish() {
        LogUtils.logi( "finish ");
        Intent i = new Intent();
        Bundle bundle = new Bundle();
        bundle.putString(ChamberModeMainActivity.FRONT_CAMERA_RESULT, "front_camera_test_finish");        
        i.putExtras(bundle);
        setResult(ChamberModeMainActivity.START_FRONT_CAMERA_TEST_RESULT_CODE,i);        
        super.finish();
    }

    public void onDestroy() {        
        LogUtils.logi( "onDestroy ");
        mStatusBarManager.disable(StatusBarManager.DISABLE_NONE);
        Util.setWindowBrightness(this,WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE);
        if (mCameraDevice != null) {
            mCameraDevice.stopPreview();
            mCameraDevice = null;
            mCameraDevice.release();
        }
        if (mFrontCameraDown != null) {
            mFrontCameraDown = null;
        }        
        super.onDestroy();
    }

    private class countDownThread extends Thread{
        public countDownThread(){}

        @Override
        public void run() {
            LogUtils.logi("countDownThread  run()");
            // TODO Auto-generated method stub
            Looper.prepare();
            mFrontCameraDown = new FrontCameraDown();
            mFrontCameraDown.start();
            Looper.loop();
        }
    }
    
    private class FrontCameraDown extends CountDownTimer{

        public FrontCameraDown() {
            super(mTimeout,mTimeout);
        }

        @Override
        public void onFinish() {
            // TODO Auto-generated method stub
            LogUtils.logi("Time Out:");
            mHandler.sendEmptyMessage(FRONT_CAMERA_MSG_TEST_END);
        }

        @Override
        public void onTick(long millisUntilFinished) {
            // TODO Auto-generated method stub
        }
    }
}
